package com.globallogic.javatrainings.sergiiivanov.controller;

import com.globallogic.javatrainings.sergiiivanov.model.Personnel;
import com.globallogic.javatrainings.sergiiivanov.model.University;
import com.globallogic.javatrainings.sergiiivanov.model.UniversityFailure;
import com.globallogic.javatrainings.sergiiivanov.model.UniversityWarning;
import com.globallogic.javatrainings.sergiiivanov.resources.Messages;
import com.globallogic.javatrainings.sergiiivanov.view.PersonnelDetailsPage;

class PersonnelDetailsController extends BasicController {
    private enum States {
        DELETE_CONFIRMATION, SHOW_PERSON_PAGE, SHOW_RESUME, SHOW_ROOMS, SHOW_PERSONNEL_LIST
    }

    private int command;
    private PersonnelDetailsPage page;
    private States currentState;
    private University university;
    private Personnel person;

    @Override
    BasicController initiate(University u) throws UniversityFailure {
        this.university = u;

        if (currentState == States.SHOW_PERSONNEL_LIST) {
            return showPersonnel();
        }
        if (currentState == States.SHOW_PERSON_PAGE) {
            return showPersonInfo();
        }
        if (currentState == States.SHOW_ROOMS) {
            return manageAssignedRooms();
        }
        if (currentState == States.SHOW_RESUME) {
            return manageResume();
        }
        if (currentState == States.DELETE_CONFIRMATION) {
            return deletePerson();
        }
        currentState = States.SHOW_PERSONNEL_LIST;
        return this;
    }

    PersonnelDetailsController() {
        page = new PersonnelDetailsPage();
        university = null;
        person = null;
    }

    private BasicController addPerson() throws UniversityFailure {
        page.pageAddPerson();
        String[] form = { "Enter name: ", "Enter phone: ", "Enter email: " };
        String[] data = questionnaire(form);
        try {
            university.personnel.addPersonnel(data[0], data[1], data[2]);
        } catch (UniversityWarning e) {
            page.error("Failed to add personnel", e.getMessage());
            currentState = States.SHOW_PERSONNEL_LIST;
            return this;
        }
        try {
            person = university.personnel.getPersonnelByIndex(university.personnel.countPeople() - 1);
            currentState = States.SHOW_PERSON_PAGE;
            return this;
        } catch (UniversityWarning e) {
            page.error("Failed to open new added personnel", e.getMessage());
            currentState = States.SHOW_PERSONNEL_LIST;
            return this;
        }
    }

    private BasicController addResumeEntry() {
        if (personNotSelected())
            return this;
        page.pageAddResumeEntry();
        String[] questions = { "Year: ", "Summary: ", "Details: " };
        String[] answers = questionnaire(questions);
        try {
            person.addResumeEntry(answers);
        } catch (UniversityWarning e) {
            page.error("Failed to add entry", e.getMessage());
        }
        currentState = States.SHOW_RESUME;
        return this;
    }

    private BasicController assignNewRoom() {
        if (personNotSelected())
            return this;
        try {
            page.pageAssignRoomStep1Building(university.buildings.getBuildings().toNamesList());
            readCommand();
            int bIndex = command;
            if (bIndex < 0 || bIndex >= university.buildings.countBuildings()) {
                currentState = States.SHOW_PERSON_PAGE;
                return this;
            }
            page.pageAssignRoomStep2Room(
                    university.buildings.getBuildingByIndex(bIndex).getRooms().toNamesList()
                    );
            readCommand();
            if (command < 0 || command >= university.buildings.getBuildingByIndex(bIndex).countRooms()) {
                currentState = States.SHOW_PERSON_PAGE;
                return this;
            }
            university.buildings.getBuildingByIndex(bIndex).getRoomByIndex(command).setResponsiblePerson(person);
        } catch (Exception e) {
            page.error("Failed to assign room", e.getMessage());
        }
        return this;
    }

    private BasicController changeEmail() {
        if (personNotSelected())
            return this;
        page.pageChaneEmailForm();
        try {
            person.setEmail(InputController.readString().trim());
        } catch (Exception e) {
            page.error("Failed to update email",
                    e.getMessage());
        }
        currentState = States.SHOW_PERSON_PAGE;
        return this;
    }

    private BasicController changeName() {
        if (personNotSelected())
            return this;
        page.pageChangeNameForm();
        try {
            person.setName(InputController.readString().trim());
        } catch (Exception e) {
            page.error("Failed to update name", e.getMessage());
        }
        currentState = States.SHOW_PERSON_PAGE;
        return this;
    }

    private BasicController changePhone() {
        if (personNotSelected())
            return this;
        page.pageUpdatePhoneForm();
        try {
            person.setMobile(InputController.readString().trim());
        } catch (Exception e) {
            page.error("Failed to update phone", e.getMessage());
        }
        currentState = States.SHOW_PERSON_PAGE;
        return this;
    }

    private BasicController deletePerson() {
        if (personNotSelected())
            return this;
        page.pageConfirmPersonDeletion();
        if (yes()) {
            try {
                university.personnel.removePerson(person);
                currentState = States.SHOW_PERSONNEL_LIST;
                return this;
            } catch (Exception e) {
                page.error("Failed to delete personnel", e.getMessage());
            }
        }
        currentState = States.SHOW_PERSON_PAGE;
        return this;
    }

    private BasicController manageAssignedRooms() throws UniversityFailure {
        if (personNotSelected())
            return this;
        String[] assignedRooms;
        assignedRooms = person.getAssignedRooms().toNamesList();
        page.pageShowAssignedRooms(person.getName(), assignedRooms);
        readCommand();
        if (command < 1 || command > assignedRooms.length + 1) {
            currentState = States.SHOW_PERSON_PAGE;
            return this;
        }
        if (command == assignedRooms.length + 1) {
            return assignNewRoom();
        }
        try {
            person.getAssignedRooms().get(command - 1).setResponsiblePerson(null);
        } catch (Exception e) {
            page.error("Failed to unassign room", e.getMessage());
        }
        return this;
    }

    private BasicController manageResume() throws UniversityFailure {
        if (personNotSelected())
            return this;
        String[][] resume;
        resume = person.getResumePrint();
        page.pageResume(resume);
        readCommand();
        if (command == 0 || command > (resume.length + 1)) {
            currentState = States.SHOW_PERSON_PAGE;
            return this;
        }
        if (command == resume.length + 1) {
            return addResumeEntry();
        }
        if (command > 1 && command <= resume.length) {
            try {
                person.removeResumeEntry(command - 1);
            } catch (UniversityWarning e) {
                page.error("Failed to remove resume entry", e.getMessage());
                return this;
            }
        }
        currentState = States.SHOW_RESUME;
        return this;
    }

    private void readCommand() {
        command = InputController.readInt();
    }

    private BasicController showPersonInfo() {
        if (personNotSelected())
            return this;
        String[] actionsMenu = {
                Messages.MENU_BACK, // 0
                "Show assigned rooms", // 1
                "Show resume", // 2
                "Update responcibilities", // 3
                "Change phone", // 4
                "Change email", // 5
                "Change name", // 6
                "Delete personnel" // 7
        };
        page.pageShowPersonDetailsHeader(university.getTitle());
        page.pagePersonDetails(person.getName(), person.getMobile(), person.getEmail());
        page.pageResponcililities(person.getResponcibilities());
        page.pageShowPersonDetailsMenu(actionsMenu);
        readCommand();
        switch (command) {
        case 0:
            return null;
        case 1:
            currentState = States.SHOW_ROOMS;
            return this;
        case 2:
            currentState = States.SHOW_RESUME;
            return this;
        case 3:
            return updateResponcibilities();
        case 4:
            return changePhone();
        case 5:
            return changeEmail();
        case 6:
            return changeName();
        case 7:
            return deletePerson();

        default:
            return this;
        }
    }

    private BasicController showPersonnel() throws UniversityFailure {
        String[] personnel;
        personnel = university.personnel.getPersonnelList();
        page.pageShowPersonnelList(university.getTitle(),
                personnel);
        readCommand();
        int menuItems = 2 + personnel.length;
        int offset = 1;
        if (command >= menuItems) {
            return this;
        }
        if (command == 0 || command > menuItems) {
            return null;
        }
        if (command == (menuItems - 1)) {
            return addPerson();
        }
        try {
            person = university.personnel.getPersonnelByIndex(command - offset);
        } catch (UniversityWarning e) {
            page.error("Failed to get personnel data", e.getMessage());
            currentState = null;
            return this;
        }
        currentState = States.SHOW_PERSON_PAGE;
        return this;
    }

    private BasicController updateResponcibilities() {
        if (personNotSelected())
            return this;
        page.pageUpdateResponcibilities();
        try {
            person.setResponcibilities(InputController.readString().trim());
        } catch (Exception e) {
            page.error("Failed to update Responcibilities", e.getMessage());
        }
        currentState = States.SHOW_PERSON_PAGE;
        return this;
    }

    private boolean personNotSelected() {
        if (person == null) {
            page.showWarning("Person is not selected");
            currentState = null;
            return true;
        }
        ;
        return false;
    }
}
